//
//  HansPinYin.m
//  KidReading
//
//  Created by telen on 15/1/5.
//  Copyright (c) 2015年 刘赞黄Telen. All rights reserved.
//

#import "HansPinYin.h"

#pragma mark- 模拟库
typedef unichar TCHAR;
unsigned int _tcslen(unichar* f)
{
    long  length = 0;
    while(*f)
    {
        length++;
        f++;
    }
    return length;
}

void _tcscpy(unichar* to, unichar* from)
{
    unsigned length = _tcslen(from);
    if (length > 0) {
        memcpy(to, from, sizeof(unichar)*length);
    }
}

void _tcsncat(unichar* to, unichar* from, int n)
{
    long length = _tcslen(to);
    if (length > 0) {
        memcpy(&to[length], from, sizeof(unichar)*n);
    }
    to[length+n] = '\0';
}

void CharLower(unichar* f)
{
    while (*f) {
        *f = tolower(*f);
        f++;
    }
}

NSString* _T(char* s)
{
    long length = strlen(s);
    unichar f[length+1];
    for (long i = 0; i< length; i++) {
        f[i] = s[i];
    }
    f[length] = '\0';
    NSString* str = [NSString stringWithCharacters:f length:length];
    return str;
}

int _tcscmp(unichar* f, NSString* str)
{
    long length = _tcslen(f);
    NSString* sf = [NSString stringWithCharacters:f length:length];
    return [sf compare:str];
}

unichar* _tcsstr(unichar* f, char* s)
{
    NSString* str = _T(s);
    long length = _tcslen(f);
    NSString* sf = [NSString stringWithCharacters:f length:length];
    NSRange range = [sf rangeOfString:str];
    if (range.length == str.length) {
        return &f[range.location];
    }
    return NULL;
}

void _tcscat(unichar* f, char* s)
{
    long length = strlen(s);
    long i = _tcslen(f);
    for (long x=0; x<length; x++) {
        f[i+x] = s[x];
    }
}

void _tcscat_(unichar* f, unichar* s)
{
    long length = _tcslen(s);
    long i = _tcslen(f);
    for (long x=0; x<length; x++) {
        f[i+x] = s[x];
    }
}

#pragma mark-

char * InitCPhonetic[]={"zh","ch","sh","b","p","m","f","d",
    "t","n","l","g","k","h","j","q",
    "x","r","z","c","s","y","w",
    "A","E","O"};
int InitCPhoneticSize=23;

struct FINALSCPHONETIC
{
    char *key;
    int	tone;
};
struct FINALSCPHONETIC FinalsCPhonetic[]= {{"uang",2},{"ueng",2},{"iang",2},{"iong",2},{"ing",1},{"uai",2},
    {"ang",1},{"eng",1},{"ong",1},{"ian",2},{"iao",2},{"uan",2},{"van",2},
    {"er",1},{"ai",1},{"ei",1},{"ao",1},{"ou",1},{"an",1},{"en",1},
    {"ua",2},{"ve",2},{"uo",2},{"ue",2},{"ui",2},{"vi",2},{"ia",2},{"ie",2},{"iu",2},
    {"iv",2},{"in",1},{"un",1},{"vn",1},
    {"a",1},{"o",1},{"e",1},{"i",1},{"u",1},{"v",1},
    {"%",1}, {"m",1}, {"ng",1}, {"n",1},{"%",1}};

int FinalsCPhoneticSize=43;//39;



unichar* SkipSpace(unichar* buf)
{
    if (!buf)
        return 0;
    while (*buf&&(/**buf==' '||*/*buf=='\t')) buf++;
    return *buf?buf:0;
}


unichar* GetWord(unichar* buf, unichar* word)
{
    if (NULL == buf || NULL == word)
        return 0;
    
    *word=0;
    buf = SkipSpace(buf);
    if (!buf) return 0;
    
    unichar* f;
    f = buf;
    while(*f)
    {
        if (*f<='9'&&*f>='0')
        {
            memcpy(word, buf, (f-buf+1)*sizeof(TCHAR));
            word[f-buf+1] = '\0';
            return f+1;
        }
        f++;
    }
    /*End edit 2001-6-28 11:00:02 */
    
    memcpy(word, buf, (f-buf)*sizeof(TCHAR));
    word[f-buf]='\0';
    
    return NULL;
}

BOOL ConvertChiPinYin(TCHAR* str, TCHAR* outStr)
{

    if( NULL == str || '\0' == str[0] ||
       NULL == outStr || _tcslen(str)==0)
        return FALSE;
    
    BOOL bUpper = FALSE,
    bUpperAndZhuDiao = FALSE;
    TCHAR *w,*w1,*p,*s;
    TCHAR word[100];
    int n=-1,m=-1;
    int i, nCh=0;
    *outStr=0;
    w = str;
    
    while ((w1=GetWord(w,word),*word))
    {
        p = word+_tcslen(word)-1;

        // add by sbd ∂˘ªØ“Ù
        char tc='\0';
        if(_tcslen(word)>=2)
            tc = *(word+_tcslen(word)-2);

        if(tc!='\0' && tc=='r')
        {
            *(word+_tcslen(word)-2) = *p;
            *p = '\0';
        }
        
        // ÷ÿ–¬ªÒ»° ˝◊÷
        p = word+_tcslen(word)-1;
        // end
        if (*p>='0'&&*p<='9')
            n = *p-'0';
        else
        {
            _tcscpy(outStr, str);
            n = 0;
            return FALSE;
        }
        nCh = 0;
        *p = '\0';
        s = w;
        w = w1;
        //		if ( w ) w ++;
        
        p = word;
        while(p[0] == '-' || p[0] == ' ' || p[0] == 0x2019)
        {
            _tcsncat(outStr,p, 1);
            p++;
        }

        bUpper = ('A' <= p[0] && p[0] <= 'Z') ;
        bUpperAndZhuDiao = ('A' == p[0] || 'E' == p[0] || 'O' == p[0]) ;
        
        CharLower(word);
        
        BOOL isLVE = FALSE;
        if(!_tcscmp(p, _T("lve")) || !_tcscmp(p, _T("nve")) )
            isLVE = TRUE;
        BOOL bNV = FALSE;
        if( !_tcscmp(p, _T("nv")) && 0 == n )
            bNV = TRUE;
        for (i=0;i<InitCPhoneticSize;i++)
        {
            if (_tcsstr(p+nCh,InitCPhonetic[i])==p)
            {
                if(!('\0' == (p+nCh+strlen(InitCPhonetic[i]))[0] ||  'g' == (p+nCh+strlen(InitCPhonetic[i]))[0]) )
                {
                    p += strlen(InitCPhonetic[i]);
                    _tcscat(outStr,InitCPhonetic[i]);
                    
                    int nUpperIndex = _tcslen(outStr) - strlen(InitCPhonetic[i]);
                    if(bUpper && ('a' <= outStr[nUpperIndex] && outStr[nUpperIndex] <= 'z') && !bUpperAndZhuDiao)
                        outStr[nUpperIndex] += ('A'-'a');//-= 0x20;
                    
                }
                break;
            }
        }
        
        m = -1;
        /*
         if( '\0' == (p+nCh)[0] || 'g' == (p+nCh)[0])
         {
         p = word;//lpTemp;//word+_tcslen(word)-1;
         }
         //*/
        for (i=0;i<FinalsCPhoneticSize;i++)
        {
            if (_tcscmp(p+nCh,_T(FinalsCPhonetic[i].key))==0)
            {
                m = FinalsCPhonetic[i].tone;
                break;
            }
        }
        
        switch (p[m-1])
        {
            case 'a':
            {
                if(bUpperAndZhuDiao && 1 == m)
                {//¥Û–¥A¥¯◊¢µÙ
                    switch (n)
                    {
                        case 0:
                            p[m-1] = 'A';
                            break;
                        case 1:
                            p[m-1] = 0x1D00;
                            break;
                        case 2:
                            p[m-1] = 0x1D01;
                            break;
                        case 3:
                            p[m-1] = 0x1D02;
                            break;
                        case 4:
                            p[m-1] = 0x1D03;
                            break;
                        default:
                            break;
                    }
                    
                }
                else
                {
                    switch (n)
                    {
                        case 0:
                            p[m-1] = 0x00A8;//'Z';
                            break;
                        case 1:
                            p[m-1] = 0x00A9;//'C';
                            break;
                        case 2:
                            p[m-1] = 0x00AA;//'E';
                            break;
                        case 3:
                            p[m-1] = 0x00AB;//'K';
                            break;
                        case 4:
                            p[m-1] = 0x00AC;//'P';
                            break;
                        default:
                            break;
                    }
                }
            }
                break;
            case 'e':
                if(bUpperAndZhuDiao && 1 == m)
                {//¥Û–¥E¥¯◊¢µÙ
                    switch (n)
                    {
                        case 0:
                            p[m-1] = 'E';
                            break;
                        case 1:
                            p[m-1] = 0x1D04;
                            break;
                        case 2:
                            p[m-1] = 0x1D05;
                            break;
                        case 3:
                            p[m-1] = 0x1D06;
                            break;
                        case 4:
                            p[m-1] = 0x1D07;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    switch (n)
                    {
                        case 0:
                            p[m-1] = '#';
                            break;
                        case 1:
                            p[m-1] = '$';
                            break;
                        case 2:
                            p[m-1] = '+';
                            break;
                        case 3:
                            p[m-1] = '0';
                            break;
                        case 4:
                            p[m-1] = '1';
                            break;
                        default:
                            break;
                    }
                }
                break;
            case 'i':
                switch (n)
            {
                case 0:
                    //				p[m-1] = '!';
                    break;
                case 1:
                    p[m-1] = 0x00B2;//'I';
                    break;
                case 2:
                    p[m-1] = '/';
                    break;
                case 3:
                    p[m-1] = '*';
                    break;
                case 4:
                    p[m-1] = '\\';
                    break;
                default:
                    break;
            }
                break;
            case 'o':
                if(bUpperAndZhuDiao && 1 == m)
                {//¥Û–¥O¥¯◊¢µÙ
                    switch (n)
                    {
                        case 0:
                            p[m-1] = 'O';
                            break;
                        case 1:
                            p[m-1] = 0x1D08;
                            break;
                        case 2:
                            p[m-1] = 0x1D09;
                            break;
                        case 3:
                            p[m-1] = 0x1D0A;
                            break;
                        case 4:
                            p[m-1] = 0x1D0B;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    switch (n)
                    {
                        case 0:
                            p[m-1] = '2';
                            break;
                        case 1:
                            p[m-1] = '3';
                            break;
                        case 2:
                            p[m-1] = '4';
                            break;
                        case 3:
                            p[m-1] = '5';
                            break;
                        case 4:
                            p[m-1] = '6';
                            break;
                        default:
                            break;
                    }
                }
                break;
            case 'u':
                switch (n)
            {
                case 0:
                    p[m-1] = '7';
                    break;
                case 1:
                    p[m-1] = '8';
                    break;
                case 2:
                    p[m-1] = '9';
                    break;
                case 3:
                    p[m-1] = '<';
                    break;
                case 4:
                    p[m-1] = '=';
                    break;
                default:
                    break;
            }
                break;
            case 'v':
                switch (n)
            {
                case 0:
                    p[m-1] = '>';
                    break;
                case 1:
                    p[m-1] = '?';
                    break;
                case 2:
                    p[m-1] = 0x00AF;//'A';
                    break;
                case 3:
                    p[m-1] = 0x00B0;//'F';
                    break;
                case 4:
                    p[m-1] = 0x00B1;//'L';
                    break;
                case 5:
                    p[m-1] = 0x00AE;//'V';
                    break;
                default:
                    break;
            }
                break;
            case 'm':
                switch (n)
            {
                case 0:
                    p[m-1] = 'm';
                    break;
                case 1:
                    p[m-1] = 0x00C7;
                    break;
                case 2:
                    p[m-1] = 0x00C8;
                    break;
                case 3:
                    p[m-1] = 0x00C9;
                    break;
                case 4:
                    p[m-1] = 0x00CA;
                    break;
                default:
                    break;
            }
                break;
            case 'n':
                switch (n)
            {
                case 0:
                    p[m-1] = 'n';
                    break;
                case 1:
                    p[m-1] = 0x00CB;
                    break;
                case 2:
                    p[m-1] = 0x00CC;
                    break;
                case 3:
                    p[m-1] = 0x00CD;
                    break;
                case 4:
                    p[m-1] = 0x00CE;
                    break;
                default:
                    break;
            }
                break;
            case '%':
                switch (n)
            {
                case 0:
                    p[m-1] = 0x00E7;
                    break;
                case 1:
                    p[m-1] = 0x00E8;
                    break;
                case 2:
                    p[m-1] = 0x00E9;
                    break;
                case 3:
                    p[m-1] = 0x00EA;
                    break;
                case 4:
                    p[m-1] = 0x00EB;
                    break;
                default:
                    break;
            }
                break;
        }
        if(isLVE)
        {
            p[m-2] = 0x00AE;//'V';
            isLVE = FALSE;
        }
        if(bNV)
        {
            p[m-1] = 0x00AE;//'V';
            bNV = FALSE;
        }
        
        _tcscat_(outStr,p);
        // ∂˘ªØ“Ù
        if(tc!='\0' && tc=='r')
            _tcscat(outStr, "r");
        
        if (w)
        {
            //_tcscat(outStr, _T(" "));
        }
        
    }
//    TrimLeft(outStr);
//    TrimRight(outStr);
    return TRUE;
    
}

@implementation HansPinYin

- (void)dealloc
{
    self.pinyin_number = nil;
    self.pinyin_ttf = nil;
}

+ (NSString*) getStringFormShort:(unichar*)sc
{
    long length = _tcslen(sc);
    NSString* string = [NSString stringWithCharacters:sc length:length];
    return string;
}

+ (HansPinYin *)convertToPinyinTTF_withPinyinNumber:(NSString *)py_number
{
    if (!py_number
        || [py_number isEqualToString:@""]) {
        return nil;
    }
    NSString *regex = @"^[A-Za-z0-9 ]+$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    if (![predicate evaluateWithObject:py_number]) {
        NSLog(@"拼音 格式不符合要求");
        return nil;
    }
    HansPinYin* hpy = [[self alloc] init];
    hpy.pinyin_number = py_number;
    //
//    py_number = @"hao3 gao1";
    unichar o[100];
    memset(o, 0, 100*sizeof(unichar));
    for (int i=0; i<py_number.length; i++) {
        o[i] = py_number.UTF8String[i];
    }
    //
    unichar c[100];
    memset(c, 0, 100*sizeof(unichar));
//    c[0] = 0x00AA;
    ConvertChiPinYin(o, c);
    hpy.pinyin_ttf = [self getStringFormShort:c];
    //
    return hpy;
}

@end
